package com.huilian.iotbox.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.huilian.iotbox.admin.dao.MemberStoreBalanceDao;
import com.huilian.iotbox.admin.service.*;
import com.huilian.iotbox.data.common.ServerResponse;
import com.huilian.iotbox.data.dto.IntegralTaskDto;
import com.huilian.iotbox.data.dto.MemberIntegralRecordDto;
import com.huilian.iotbox.data.dto.MemberStoreBalanceDto;
import com.huilian.iotbox.data.enums.IntegralTaskTypeEnum;
import com.huilian.iotbox.data.enums.MchTypeEnum;
import com.huilian.iotbox.data.enums.MemberIntegralRecordBusinessTypeEnum;
import com.huilian.iotbox.data.enums.MemberIntegralRecordTypeEnum;
import com.huilian.iotbox.data.po.MemberStoreBalance;
import com.huilian.iotbox.data.po.Order;
import com.huilian.iotbox.data.vo.ActivityOrderVo;
import com.huilian.iotbox.data.vo.IntegralTaskVo;
import com.huilian.iotbox.data.vo.MemberIntegralRecordVo;
import com.huilian.iotbox.data.vo.MemberStoreBalanceVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;

/**
 * @author 谢洛涛
 * @date 2021/3/31 13:15
 */
@Slf4j
@Service
public class MemberStoreBalanceServiceImpl implements MemberStoreBalanceService {

    // 增加或减少游戏币重试次数
    private static int count = 10;
    @Autowired
    private MemberStoreBalanceDao memberStoreBalanceDao;

    @Override
    public ServerResponse consumeMember(MemberStoreBalance memberStoreBalance) {
        return ServerResponse.createBySuccess(memberStoreBalanceDao.consumeMember(memberStoreBalance));
    }

    @Override
    public Integer findDayMemberNewNumByStoreId(MemberStoreBalanceDto memberStoreBalanceDto) {
        return memberStoreBalanceDao.findDayMemberNewNumByStoreId(memberStoreBalanceDto);
    }

    @Override
    public MemberStoreBalanceVo findBalance(MemberStoreBalanceDto memberStoreBalanceDto) {
        return memberStoreBalanceDao.findMemberStoreBalanceByMerchantStoreId(memberStoreBalanceDto);
    }

    @Override
    public Integer updateMemberStoreBalance(MemberStoreBalance memberStoreBalance) {
        return memberStoreBalanceDao.updateMemberStoreBalance(memberStoreBalance);
    }

    @Override
    public void insert(MemberStoreBalance memberStoreBalance) {
        memberStoreBalanceDao.insert(memberStoreBalance);
    }

    /**
     * 增加或减少游戏币前校验参数
     *
     * @param rechargeNum          充值游戏币数量
     * @param donateNum            赠送游戏币数量
     * @param memberStoreBalanceId 会员场地关联id
     * @param memberId             会员id
     * @param userId               商家id
     * @param merchantStoreId      场地id
     * @return
     */
    @Override
    public MemberStoreBalance addOrReduceMemberStoreBalanceBeforeCheckParam(int rechargeNum, int donateNum, long memberStoreBalanceId, long memberId, int userId, int merchantStoreId) {

        if (rechargeNum == 0 && donateNum == 0) {
            log.error("充值、赠送游戏币数量为0。rechargeNum=" + rechargeNum);
            log.error("充值、赠送游戏币数量为0。donateNum=" + donateNum);
            throw new RuntimeException("充值、赠送游戏币数量为0");
        }

        MemberStoreBalance memberStoreBalance = memberStoreBalanceDao.findOneMemberStoreBalanceById(memberStoreBalanceId);
        if (StringUtils.isEmpty(memberStoreBalance)) {
            log.error("充值、赠送游戏币数量为0。memberStoreBalanceId=" + memberStoreBalanceId);
            throw new RuntimeException("会员场地关联id无效");
        }

        if (memberId != memberStoreBalance.getMemberId()) {
            log.error("充值、赠送游戏币数量为0。memberId=" + memberId);
            throw new RuntimeException("会员id不匹配");
        }

        if (userId != memberStoreBalance.getUserId()) {
            log.error("充值、赠送游戏币数量为0。userId=" + userId);
            throw new RuntimeException("会员场地关联id无效");
        }

        if (merchantStoreId != memberStoreBalance.getMerchantStoreId()) {
            log.error("充值、赠送游戏币数量为0。merchantStoreId=" + merchantStoreId);
            throw new RuntimeException("会员场地关联id无效");
        }

        return memberStoreBalance;
    }

    /**
     * 增加游戏币余额
     *
     * @param runCount             当前第几次运行，传值 1
     * @param rechargeNum          充值游戏币数量
     * @param donateNum            赠送游戏币数量
     * @param memberStoreBalanceId 会员场地关联id
     * @param memberId             会员id
     * @param userId               商家id
     * @param merchantStoreId      场地id
     * @return
     */
    @Override
    public int addMemberStoreBalance(int runCount, int rechargeNum, int donateNum, long memberStoreBalanceId, long memberId, int userId, int merchantStoreId) {
        long begin = System.currentTimeMillis();
        log.info(memberStoreBalanceId + "线程" + Thread.currentThread().getName() + "第" + runCount + "次执行");
        MemberStoreBalance memberStoreBalance
                = addOrReduceMemberStoreBalanceBeforeCheckParam(rechargeNum, donateNum, memberStoreBalanceId, memberId, userId, merchantStoreId);

        int row = memberStoreBalanceDao.addMemberStoreBalance(rechargeNum, donateNum, memberStoreBalanceId, memberId, userId, merchantStoreId, memberStoreBalance.getVersionId());

        if (row == 0 && runCount < count) {
            log.info(memberStoreBalanceId + "业务耗时：" + (System.currentTimeMillis() - begin) + "ms");
            return this.addMemberStoreBalance(runCount + 1, rechargeNum, donateNum, memberStoreBalanceId, memberId, userId, merchantStoreId);
        } else if (row == 0 && runCount >= count) {
            log.info(memberStoreBalanceId + "执行次数达到" + count + "次，row=0");
        }
        log.info(memberStoreBalanceId + "业务耗时：" + (System.currentTimeMillis() - begin) + "ms");
        return row;
    }

    /**
     * 减少游戏币余额
     *
     * @param runCount             当前第几次运行，传值 1
     * @param rechargeNum          充值游戏币数量
     * @param donateNum            赠送游戏币数量
     * @param memberStoreBalanceId 会员场地关联id
     * @param memberId             会员id
     * @param userId               商家id
     * @param merchantStoreId      场地id
     * @return
     */
    @Override
    public int reduceMemberStoreBalance(int runCount, int rechargeNum, int donateNum, Long memberStoreBalanceId, Long memberId, Integer userId, Integer merchantStoreId) {
        long begin = System.currentTimeMillis();
        log.info(memberStoreBalanceId + "线程" + Thread.currentThread().getName() + "第" + runCount + "次执行");
        MemberStoreBalance memberStoreBalance
                = addOrReduceMemberStoreBalanceBeforeCheckParam(rechargeNum, donateNum, memberStoreBalanceId, memberId, userId, merchantStoreId);

        if (memberStoreBalance.getRechargeBalance() < rechargeNum || memberStoreBalance.getDonateBalance() < donateNum) {
            if (runCount >= count) {
                return 0;
            }
            return this.reduceMemberStoreBalance(runCount + 1, rechargeNum, donateNum, memberStoreBalanceId, memberId, userId, merchantStoreId);
        }

        int row = memberStoreBalanceDao.reduceMemberStoreBalance(rechargeNum, donateNum, memberStoreBalanceId, memberId, userId, merchantStoreId, memberStoreBalance.getVersionId());

        if (row == 0 && runCount < count) {
            log.info(memberStoreBalanceId + "业务耗时：" + (System.currentTimeMillis() - begin) + "ms");
            return this.reduceMemberStoreBalance(runCount + 1, rechargeNum, donateNum, memberStoreBalanceId, memberId, userId, merchantStoreId);
        } else if (row == 0 && runCount >= count) {
            log.info(memberStoreBalanceId + "执行次数达到" + count + "次，row=0");
        }
        log.info(memberStoreBalanceId + "业务耗时：" + (System.currentTimeMillis() - begin) + "ms");
        return row;
    }

    @Override
    public int addMemberStoreChargeBalance(int runCount, MemberStoreBalance memberStoreBalance) {
        long begin = System.currentTimeMillis();
        log.info(memberStoreBalance.getId() + "线程" + Thread.currentThread().getName() + "第" + runCount + "次执行");
        MemberStoreBalance msb
                = addOrReduceMemberStoreChargeBalanceBeforeCheckParam(memberStoreBalance);

        memberStoreBalance.setVersionId(msb.getVersionId());
        int row = memberStoreBalanceDao.addMemberStoreChargeBalance(memberStoreBalance);

        if (row == 0 && runCount < count) {
            log.info(memberStoreBalance.getId() + "业务耗时：" + (System.currentTimeMillis() - begin) + "ms");
            return this.addMemberStoreChargeBalance(runCount + 1, memberStoreBalance);
        } else if (row == 0 && runCount >= count) {
            log.info(memberStoreBalance.getId() + "执行次数达到" + count + "次，row=0");
        }
        log.info(memberStoreBalance.getId() + "业务耗时：" + (System.currentTimeMillis() - begin) + "ms");
        return row;
    }

    /**
     * 增加或减少余额前校验参数
     *
     * @return
     */
    @Override
    public MemberStoreBalance addOrReduceMemberStoreChargeBalanceBeforeCheckParam(MemberStoreBalance memberStoreBalance) {

        if (memberStoreBalance.getMoneyRechargeBalance().compareTo(BigDecimal.ZERO) == 0 && memberStoreBalance.getMoneyDonateBalance().compareTo(BigDecimal.ZERO) == 0) {
            log.error("人民币充值余额为0。moneyRechargeBalance=" + memberStoreBalance.getMoneyRechargeBalance());
            log.error("人民币赠送余额为0。moneyDonateBalance=" + memberStoreBalance.getMoneyDonateBalance());
            throw new RuntimeException("人民币充值、赠送余额为0");
        }

        MemberStoreBalanceDto memberStoreBalanceDto = new MemberStoreBalanceDto();
        memberStoreBalanceDto.setId(memberStoreBalance.getId());
        MemberStoreBalance msb = memberStoreBalanceDao.findOneMemberStoreBalanceById(memberStoreBalance.getId());
        if (StringUtils.isEmpty(msb)) {
            log.error("人民币充值、赠送余额为0。memberStoreBalanceId=" + memberStoreBalance.getId());
            throw new RuntimeException("会员场地关联id无效");
        }

        if (memberStoreBalance.getMemberId().compareTo(msb.getMemberId()) != 0) {
            log.error("人民币充值、赠送余额为0。memberId=" + memberStoreBalance.getMemberId());
            throw new RuntimeException("会员id不匹配");
        }

        if (memberStoreBalance.getUserId().compareTo(msb.getUserId()) != 0) {
            log.error("人民币充值、赠送余额为0。userId=" + memberStoreBalance.getUserId());
            throw new RuntimeException("会员场地关联id无效");
        }

        if (memberStoreBalance.getMerchantStoreId().compareTo(msb.getMerchantStoreId()) != 0) {
            log.error("人民币充值、赠送余额为0。merchantStoreId=" + memberStoreBalance.getMerchantStoreId());
            throw new RuntimeException("会员场地关联id无效");
        }

        return msb;
    }

    @Override
    public Integer findDayMemberOldNumByStoreId(MemberStoreBalanceDto memberStoreBalanceDto) {
        return memberStoreBalanceDao.findDayMemberOldNumByStoreId(memberStoreBalanceDto);
    }
}
